package com.mxpio.erp.inventory.service.impl;

import com.mxpio.erp.common.enums.*;
import com.mxpio.erp.common.inventory.entity.*;
import com.mxpio.erp.common.inventory.service.*;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.common.util.SpringUtil;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.query.*;
import com.mxpioframework.system.service.SnRuleService;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Author : 吴盼盼
 * @Datetime : 2022/10/6 21:21
 * @Desc :
 * @Modor :  Modifytime:
 * @modDesc :
 */
@Service
public class InventoryServiceImpl extends BaseServiceImpl<Inventory> implements InventoryService {
    @Autowired
    private InventoryItemService inventoryItemService;
    @Autowired
    private VInvLotStockService vInvLotStockService;

    @Autowired
    private InventoryReviewService inventoryReviewService;
    @Override
    @Transactional
    public Result<Inventory> saveInventory(Inventory inventory) {
        if (StringUtils.isBlank(inventory.getInventoryCode())){//新增
            SnRuleService snRuleService = SpringUtil.getBean(SnRuleService.class);
            String expression = "IC";
            String yearmonth = DateUtils.formatDate(new Date(), "yyyyMM");
            String bizNo = (String) snRuleService.execute(expression+yearmonth+"###", null);
            inventory.setInventoryCode(bizNo);
            inventory.setInventoryStatus(InventoryEnums.InventoryStatus.CREATE.getStatusCode());//开立状态
        }else{//更新
            Criteria c = Criteria.create().addCriterion("inventoryCode", Operator.EQ, inventory.getInventoryCode());
            inventoryItemService.removeBatch(InventoryItem.class, c);//
        }
        save(inventory);//保存主单
        //生成criteria
        Criteria c = CriteriaUtils.json2Criteria(inventory.getCriteria());
        if (c==null){
            throw new MBootException("提交数据中没有维度数据！");
        }
        //c.addCriterion("whCode",Operator.EQ,inventory.getWhCode());//指定默认仓库，由前端传值
        List<VInvLotStock> invFlows = vInvLotStockService.listByLot(c);
        List<InventoryItem> addItems = new ArrayList<>();
        if (invFlows.size()>0){
            int i = 0;
            Map<String,Item> dbItemMap = new HashMap<>();
            for (VInvLotStock stock:invFlows){
                i++;
                Item dbItem = null;
                if (dbItemMap.containsKey(stock.getItemCode())){
                    dbItem = dbItemMap.get(stock.getItemCode());
                }else{
                    dbItem = JpaUtil.linq(Item.class).idEqual(stock.getItemCode()).findOne();
                    dbItemMap.put(stock.getItemCode(),dbItem);
                }
                InventoryItem item = new InventoryItem();
                item.setInventoryCode(inventory.getInventoryCode());
                item.setItemCode(stock.getItemCode());
                item.setLotNo(stock.getLotNo());
                item.setWhCode(stock.getWhCode());
                item.setQuantity(stock.getQuantity());
                item.setLineNo(i+"");
                //关联物料冗余信息字段
                item.setItemName(dbItem.getItemName());
                item.setItemSpec(dbItem.getItemSpec());
                item.setItemGroupCode(dbItem.getItemGroupCode());
                item.setUnitCode(dbItem.getUnitCode());
                item.setDrawingNo(dbItem.getDrawingNo());
                addItems.add(item);
            }
            inventoryItemService.save(addItems);//保存盘点任务明细
        }else{
            throw new MBootException("数据维度没有对应的库存数据，不能生成对应盘点任务");
            //return Result.error("维度没有对应的库存数据");
        }
        inventory.setItemList(addItems);
        return Result.OK(inventory);
    }

    @Override
    @Transactional
    public Result<Inventory> review(String inventoryCode, InventoryReview inventoryReview) {
        Inventory byId = this.getById(Inventory.class, inventoryCode);
        if (!StringUtils.equals(byId.getInventoryStatus(),InventoryEnums.InventoryStatus.REVIEW.getStatusCode())){
            return Result.error("仅待复核状态的数据可以执行复核操作");
        }
        if (StringUtils.equals(inventoryReview.getReviewOpinion(), AuditEnums.Purc.OK.getTypeCode())){
            byId.setInventoryStatus(InventoryEnums.InventoryStatus.COMPLETE.getStatusCode());//完成
            this.update(byId);
            inventoryReview.setInventoryCode(inventoryCode);
            inventoryReviewService.save(inventoryReview);
            Criteria c = Criteria.create().addCriterion("inventoryCode", Operator.EQ, inventoryCode);
            List<InventoryItem> items = inventoryItemService.list(InventoryItem.class, c);
            Map<String,WarehouseOrder> lossWOrderMap = new HashMap<>();
            Map<String,List<WarehouseOrderLine>> lossWOrderLineMap = new HashMap<>();
            Map<String,WarehouseOrder> plusWOrderMap = new HashMap<>();
            Map<String,List<WarehouseOrderLine>> plusWOrderLineMap = new HashMap<>();
            //生成调差/调盈单
            for (InventoryItem item : items){
                if (StringUtils.equals(item.getHandleMethod(),InventoryEnums.InventoryHandleMethod.LOSS.getStatusCode())){
                    if (!lossWOrderMap.containsKey(item.getWhCode())){
                        //仓单主单
                        WarehouseOrder wo = new WarehouseOrder();
                        wo.setAccessType(OrderEnums.AccessType.OUT.getCode());
                        wo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
                        wo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
                        wo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
                        wo.setOrderDate(new Date());
                        wo.setOriginBizNo(inventoryCode);
                        wo.setWhCode(item.getWhCode());
                        wo.setWoType(NoticeStatusEnums.NoticeType.AO_OUT.getCode());
                        lossWOrderMap.put(item.getWhCode(),wo);
                        //JpaUtil.save(wo);
                    }

                    WarehouseOrderLine line = new WarehouseOrderLine();
                    line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
                    Item dbItem = JpaUtil.linq(Item.class).idEqual(item.getItemCode()).findOne();
                    line.setItemCode(dbItem.getItemCode());
                    line.setItemName(dbItem.getItemName());
                    line.setItemSpec(dbItem.getItemSpec());
                    line.setUnitCode(dbItem.getUnitCode());
                    line.setQuantity(item.getInventoryDiffNum().abs());
                    //line.setBizNo(wo.getBizNo());
                    //line.setLineNo(1+"");
                    line.setOriginBizNo(inventoryCode);
                    line.setOriginBizLineNo(item.getLineNo());
                    line.setLotNo(item.getLotNo());
                    //JpaUtil.save(line);

                    if (!lossWOrderLineMap.containsKey(item.getWhCode())){
                        List<WarehouseOrderLine> lineList = new ArrayList<>();
                        lineList.add(line);
                        lossWOrderLineMap.put(item.getWhCode(),lineList);
                    }else{
                        lossWOrderLineMap.get(item.getWhCode()).add(line);
                    }
                }else if (StringUtils.equals(item.getHandleMethod(),InventoryEnums.InventoryHandleMethod.SURPLUS.getStatusCode())){
                    if (!plusWOrderMap.containsKey(item.getWhCode())){
                        //仓单主单
                        WarehouseOrder wo = new WarehouseOrder();
                        wo.setAccessType(OrderEnums.AccessType.IN.getCode());
                        wo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
                        wo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
                        wo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
                        wo.setOrderDate(new Date());
                        wo.setOriginBizNo(inventoryCode);
                        wo.setWhCode(item.getWhCode());
                        wo.setWoType(NoticeStatusEnums.NoticeType.AO_IN.getCode());
                        //JpaUtil.save(wo);
                        plusWOrderMap.put(item.getWhCode(),wo);
                    }

                    WarehouseOrderLine line = new WarehouseOrderLine();
                    line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
                    Item dbItem = JpaUtil.linq(Item.class).idEqual(item.getItemCode()).findOne();
                    line.setItemCode(dbItem.getItemCode());
                    line.setItemName(dbItem.getItemName());
                    line.setItemSpec(dbItem.getItemSpec());
                    line.setUnitCode(dbItem.getUnitCode());
                    line.setQuantity(item.getInventoryDiffNum().abs());
                    //line.setBizNo(wo.getBizNo());
                    //line.setLineNo(1+"");
                    line.setOriginBizNo(inventoryCode);
                    line.setOriginBizLineNo(item.getLineNo());
                    line.setLotNo(item.getLotNo());
                    //JpaUtil.save(line);
                    if (!plusWOrderLineMap.containsKey(item.getWhCode())){
                        List<WarehouseOrderLine> lineList = new ArrayList<>();
                        lineList.add(line);
                        plusWOrderLineMap.put(item.getWhCode(),lineList);
                    }else{
                        plusWOrderLineMap.get(item.getWhCode()).add(line);
                    }
                }
            }
            if (!lossWOrderMap.isEmpty()){//盘亏保存
                Set<String> whCodes = lossWOrderMap.keySet();
                for (String whCode:whCodes){
                    WarehouseOrder warehouseOrder = lossWOrderMap.get(whCode);
                    JpaUtil.save(warehouseOrder);
                    List<WarehouseOrderLine> warehouseOrderLines = lossWOrderLineMap.get(whCode);
                    for (int i = 0; i < warehouseOrderLines.size(); i++) {
                        WarehouseOrderLine line = warehouseOrderLines.get(i);
                        line.setBizNo(warehouseOrder.getBizNo());
                        line.setLineNo((i+1)+"");
                        JpaUtil.save(line);
                    }
                }
            }
            if (!plusWOrderMap.isEmpty()){//盘盈保存
                Set<String> whCodes = plusWOrderMap.keySet();
                for (String whCode:whCodes){
                    WarehouseOrder warehouseOrder = plusWOrderMap.get(whCode);
                    JpaUtil.save(warehouseOrder);
                    List<WarehouseOrderLine> warehouseOrderLines = plusWOrderLineMap.get(whCode);
                    for (int i = 0; i < warehouseOrderLines.size(); i++) {
                        WarehouseOrderLine line = warehouseOrderLines.get(i);
                        line.setBizNo(warehouseOrder.getBizNo());
                        line.setLineNo((i+1)+"");
                        JpaUtil.save(line);
                    }
                }
            }
        }else{//驳回
            byId.setInventoryStatus(InventoryEnums.InventoryStatus.READY.getStatusCode());//待盘点状态
            this.update(byId);
            inventoryReview.setInventoryCode(inventoryCode);
            inventoryReviewService.save(inventoryReview);
        }
        return Result.OK();
    }

    @Override
    @Transactional
    public Result<Inventory> saveInventoryItmes(Inventory inventory) {
        List<InventoryItem> itemList = inventory.getItemList();
        String inventoryCode = inventory.getInventoryCode();
        Inventory byId = this.getById(Inventory.class, inventoryCode);
        if (itemList.size()>0){
            inventoryItemService.update(itemList);//
            if (byId.getInventoryActualDate()==null){
                byId.setInventoryActualDate(new Date());//记录实际开始盘点时间
                this.update(byId);
            }
        }else{
            return Result.error("提交的盘点任务明细数据为空");
        }
        return Result.OK();
    }
}
